package com.house.user.service.impl;


import com.house.common.to.UserTo;
import com.house.common.utils.PageUtils;
import com.house.common.utils.Query;
import com.house.common.utils.R;
import com.house.user.dao.UserDao;
import com.house.user.entity.UserEntity;
import com.house.user.feign.AuthFeignService;
import com.house.user.service.UserService;
import com.house.user.util.IpUtils;
import com.house.user.vo.UserLoginVo;
import io.lettuce.core.dynamic.annotation.Param;
import org.apache.logging.log4j.util.Strings;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;
import java.util.Objects;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;


import javax.servlet.http.HttpServletRequest;


@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService , UserDetailsService {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private AuthFeignService authFeignService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private IpUtils ipUtils;

    @Value(value = "${portrait.host}")
    private String portrait;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<UserEntity> page = this.page(
                new Query<UserEntity>().getPage(params),
                new QueryWrapper<UserEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public R getCode(String phone) {
        //使用mq发送消息
        rabbitTemplate.convertAndSend("sendCode",phone);
        return R.ok();
    }

/*
    * @Override
    public ResponseResult login(User user) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if(Objects.isNull(authenticate)){
            throw new RuntimeException("用户名或密码错误");
        }
        //使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId().toString();
        String jwt = JwtUtil.createJWT(userId);
        //authenticate存入redis
        redisCache.setCacheObject("login:"+userId,loginUser);
        //把token响应给前端
        HashMap<String,String> map = new HashMap<>();
        map.put("token",jwt);
        return new ResponseResult(200,"登陆成功",map);
    }
    * */

    @Override
    public R login(UserLoginVo userLoginVo) {
        UsernamePasswordAuthenticationToken authenticationToken =
                new UsernamePasswordAuthenticationToken(userLoginVo.getPhone(),userLoginVo.getCode());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (Objects.isNull(authenticate)){
            return R.error();
        }
        UserEntity user = (UserEntity) authenticate.getPrincipal();
        UserTo userTo = new UserTo();
        BeanUtils.copyProperties(user,userTo);
        R r = authFeignService.createToken(userTo);
        String token = (String) r.get("token");
        return R.ok().put("token",token)
                .put("role",user.getRole()).put("name",user.getNickname());
//        return R.ok().put("token",token);
    }

/*
    @Override
    public R login(UserLoginVo userLoginVo) {
        String s = (String) redisTemplate.opsForValue().get("consume:sendCode:" + userLoginVo.getPhone());

        Integer code = null;
        if (s!= null){
            code = Integer.parseInt(s) ;
        }
        //不为空对比正确性

        if (code != null) {
            if (userLoginVo.getCode().equals(code)){
                QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
                wrapper.eq("phone",userLoginVo.getPhone());
                UserEntity user = baseMapper.selectOne(wrapper);
                //新用户，需注册
                if (user == null){
                    UserEntity userEntity = new UserEntity();
                    userEntity.setPhone(userLoginVo.getPhone());
                    userEntity.setRegTime(new Date());
                    userEntity.setPid(1L);
                    userEntity.setRole(1L);
                    userEntity.setPortrait(portrait);
                    userEntity.setNickname("用户_"+userLoginVo.getPhone());
                    userEntity.setLastLoginIp(ipUtils.getIpFromRequest(request));
                    userEntity.setLastLoginTime(new Date());
                    userEntity.setStatus(1L);
                    baseMapper.insert(userEntity);

                    UserTo userTo = new UserTo();
                    userTo.setUid(userEntity.getUid());
                    userTo.setUserName(userEntity.getNickname());
                    userTo.setPid(userEntity.getPid());

                    R token = authFeignService.createToken(userTo);

                    return R.ok("注册成功").put("token",token.get("token"))
                            .put("role",userEntity.getRole()).put("name",userEntity.getNickname());

                }else {
                    UserTo userTo = new UserTo();
                    userTo.setUid(user.getUid());
                    userTo.setUserName(user.getNickname());
                    userTo.setPid(user.getPid());

                    R token = authFeignService.createToken(userTo);

                    if (token.get("code").equals(0)){
                        user.setLastLoginTime(new Date());
                        user.setLastLoginIp(ipUtils.getIpFromRequest(request));
                        baseMapper.updateById(user);

                        return R.ok().put("token",token.get("token"))
                        .put("role",user.getRole()).put("name",user.getNickname());
                    }else {
                        return R.error(50003,"登录权限异常");
                    }


                }
            }else {
                return R.error(50002,"请核对验证码");
            }
        }else {
            return R.error(50001,"验证码不存在或已过期");
        }
    }
        */

    /**
     * 登录逻辑
     * @param phone
     * @return
     */
    @Override
    public UserDetails loadUserByUsername(String phone) {
        Object o = redisTemplate.opsForValue().get("consume:sendCode:" + phone);
        String code = (String) o;
        if(Strings.isNotEmpty(code)){
            QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
            wrapper.eq("phone",phone);
            UserEntity user = baseMapper.selectOne(wrapper);
            if (Objects.isNull(user)){
                throw new RuntimeException("手机号未注册");
            }
                user.setCode(passwordEncoder.encode(code));
                return user;
        }else {
            throw new RuntimeException("未获取验证码");
        }
    }

    /*
        public UserDetails loadUserByUsername(String username) {
        // 根据用户名查询用户
        Users admin = getAdminByUsername(username);
        if (admin != null) {
            List<Resource> resourceList = getResourceList(admin.getId());
            return new AdminUserDetails(admin,resourceList);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }
     */
}